Popular Searches
Popular Course Categories
Popular Courses

Page Methods

Page Object Model

<div class="selenium-notes">

<h1>Page Methods in Selenium Page Object Model (POM)</h1>

<p><strong>Page Methods</strong> are methods defined inside Page Object classes to represent the actions, operations, and services that a user can perform on a particular web page. In Selenium automation, Page Methods are an important part of the Page Object Model because they keep Selenium interaction logic inside page classes instead of placing locators and WebDriver commands directly inside test cases.</p>

<p>For example, instead of writing <code>driver.findElement(By.id("username")).sendKeys("admin")</code> repeatedly in different test classes, a <strong>LoginPage</strong> can provide a method such as <code>enterUsername()</code>. The test can then simply call <code>loginPage.enterUsername("admin")</code>.</p>

<p>This approach separates <strong>test logic</strong> from <strong>page interaction logic</strong>, reduces duplicate code, improves readability, and makes UI changes easier to maintain. Selenium's official documentation describes Page Objects as an abstraction that models the services offered by a page and keeps page-specific implementation details in one place.</p>

<p><strong>Course Resource:</strong> <a href="https://www.justacademy.co/course-detail/selenium-training" target="_blank" rel="noopener noreferrer">Selenium Training</a> | <a href="https://www.justacademy.co/register-for-course-demo" target="_blank" rel="noopener noreferrer">Register for Course Demo</a></p>

<hr>

<h2>1. What are Page Methods?</h2>

<p>Page Methods are reusable Java methods created inside Page Object classes. Each method normally represents one meaningful action or operation available on a web page.</p>

<p>For example, a Login Page may contain methods such as:</p>

<ul>

<li><code>enterUsername()</code></li>

<li><code>enterPassword()</code></li>

<li><code>clickLogin()</code></li>

<li><code>loginAs()</code></li>

<li><code>getErrorMessage()</code></li>

</ul>

<p>These methods hide the Selenium implementation details from the test class.</p>

<pre><code>LoginPage loginPage = new LoginPage(driver);

 

loginPage.enterUsername("admin");

loginPage.enterPassword("admin123");

loginPage.clickLogin();</code></pre>

<p>The test focuses on <strong>what action needs to be performed</strong>, while the Page Object handles <strong>how the action is performed</strong>.</p>

<hr>

<h2>2. Why are Page Methods Important?</h2>

<p>Page Methods are important because automation frameworks often contain hundreds or thousands of Selenium interactions. If those interactions are directly written in test classes, the framework becomes difficult to maintain.</p>

<ul>

<li>Reduce duplicate Selenium code.</li>

<li>Centralize page-specific operations.</li>

<li>Improve test readability.</li>

<li>Improve code reusability.</li>

<li>Separate test logic from UI interaction logic.</li>

<li>Make UI changes easier to manage.</li>

<li>Support scalable automation frameworks.</li>

<li>Make tests easier for other team members to understand.</li>

<li>Encourage object-oriented automation design.</li>

<li>Allow page workflows to be reused across multiple tests.</li>

</ul>

<hr>

<h2>3. Page Method Architecture</h2>

<pre><code>Test Class

    |

    v

Page Method

    |

    v

Page Locator

    |

    v

Selenium WebDriver

    |

    v

Web Browser

    |

    v

Application</code></pre>

<p>The test class calls a page method. The page method uses the appropriate locator and WebDriver operation to interact with the application.</p>

<hr>

<h2>4. Page Methods and POM</h2>

<p>Page Methods are one of the core implementation elements of the Page Object Model. A Page Object generally contains the locators and methods required to interact with a particular page or reusable component.</p>

<pre><code>LoginPage.java

    |

    +-- Locators

    |     +-- username

    |     +-- password

    |     +-- loginButton

    |

    +-- Page Methods

          +-- enterUsername()

          +-- enterPassword()

          +-- clickLogin()

          +-- loginAs()</code></pre>

<p>The test class does not need to know the locator details.</p>

<hr>

<h2>5. Page Method vs Test Method</h2>

<table border="1" cellpadding="8" cellspacing="0">

<tr><th>Page Method</th><th>Test Method</th></tr>

<tr><td>Belongs to a Page Object</td><td>Belongs to a test class</td></tr>

<tr><td>Handles page interaction</td><td>Validates application behavior</td></tr>

<tr><td>Contains Selenium operations</td><td>Calls Page Methods</td></tr>

<tr><td>Usually reusable</td><td>Represents a test scenario</td></tr>

<tr><td>Focuses on application services</td><td>Focuses on expected behavior</td></tr>

<tr><td>Should generally avoid test assertions</td><td>Normally contains assertions</td></tr>

</table>

<hr>

<h2>6. Simple Page Method Example</h2>

<pre><code>public class LoginPage {

 

    WebDriver driver;

 

    By username = By.id("username");

 

    public LoginPage(WebDriver driver) {

        this.driver = driver;

    }

 

    public void enterUsername(String value) {

        driver.findElement(username).sendKeys(value);

    }

}</code></pre>

<p>The test can use the method like this:</p>

<pre><code>LoginPage loginPage = new LoginPage(driver);

 

loginPage.enterUsername("admin");</code></pre>

<hr>

<h2>7. Creating a Login Page Class</h2>

<p>A Login Page commonly contains username, password, and login-button locators along with methods representing login operations.</p>

<pre><code>import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

 

public class LoginPage {

 

    private WebDriver driver;

 

    private By usernameField = By.id("username");

    private By passwordField = By.id("password");

    private By loginButton = By.id("loginButton");

 

    public LoginPage(WebDriver driver) {

        this.driver = driver;

    }

 

    public void enterUsername(String username) {

        driver.findElement(usernameField).sendKeys(username);

    }

 

    public void enterPassword(String password) {

        driver.findElement(passwordField).sendKeys(password);

    }

 

    public void clickLogin() {

        driver.findElement(loginButton).click();

    }

}</code></pre>

<hr>

<h2>8. Calling Page Methods from Test Class</h2>

<pre><code>import org.testng.annotations.Test;

 

public class LoginTest {

 

    @Test

    public void validLoginTest() {

 

        LoginPage loginPage = new LoginPage(driver);

 

        loginPage.enterUsername("admin");

        loginPage.enterPassword("admin123");

        loginPage.clickLogin();

    }

}</code></pre>

<p>The test class is now easier to read because the Selenium implementation is encapsulated inside the Page Object.</p>

<hr>

<h2>9. Method for Entering Username</h2>

<p>A dedicated method can represent the action of entering a username.</p>

<pre><code>public void enterUsername(String username) {

    driver.findElement(usernameField)

          .clear();

 

    driver.findElement(usernameField)

          .sendKeys(username);

}</code></pre>

<p>The <code>clear()</code> operation is useful when the field may already contain text.</p>

<hr>

<h2>10. Method for Entering Password</h2>

<pre><code>public void enterPassword(String password) {

    driver.findElement(passwordField)

          .clear();

 

    driver.findElement(passwordField)

          .sendKeys(password);

}</code></pre>

<p>Keeping the password interaction in the Page Object prevents the locator and WebDriver code from being duplicated across tests.</p>

<hr>

<h2>11. Method for Clicking Login</h2>

<pre><code>public void clickLogin() {

    driver.findElement(loginButton)

          .click();

}</code></pre>

<p>The test can simply call:</p>

<pre><code>loginPage.clickLogin();</code></pre>

<hr>

<h2>12. Creating a Complete Login Method</h2>

<p>Individual actions can be combined into a higher-level workflow method.</p>

<pre><code>public void login(String username, String password) {

 

    enterUsername(username);

    enterPassword(password);

    clickLogin();

}</code></pre>

<p>The test becomes:</p>

<pre><code>LoginPage loginPage = new LoginPage(driver);

 

loginPage.login("admin", "admin123");</code></pre>

<p>This is usually more expressive than exposing every low-level interaction to the test.</p>

<hr>

<h2>13. Low-Level vs High-Level Page Methods</h2>

<table border="1" cellpadding="8" cellspacing="0">

<tr><th>Type</th><th>Example</th><th>Purpose</th></tr>

<tr><td>Low-Level</td><td>enterUsername()</td><td>Performs one UI action</td></tr>

<tr><td>Low-Level</td><td>clickLogin()</td><td>Clicks one element</td></tr>

<tr><td>High-Level</td><td>login()</td><td>Performs complete login workflow</td></tr>

<tr><td>High-Level</td><td>searchProduct()</td><td>Performs complete search operation</td></tr>

<tr><td>High-Level</td><td>checkoutProduct()</td><td>Performs checkout workflow</td></tr>

</table>

<hr>

<h2>14. Returning void from Page Methods</h2>

<p>A Page Method can return <code>void</code> when the action does not need to provide a result to the caller.</p>

<pre><code>public void clickLogin() {

    driver.findElement(loginButton).click();

}</code></pre>

<p>This is appropriate for simple actions where the test does not need another object or value from the method.</p>

<hr>

<h2>15. Returning String from Page Methods</h2>

<p>A Page Method can return information obtained from the page.</p>

<pre><code>private By errorMessage = By.id("error");

 

public String getErrorMessage() {

    return driver.findElement(errorMessage)

                 .getText();

}</code></pre>

<p>The test can then validate the returned value.</p>

<pre><code>String actualMessage = loginPage.getErrorMessage();

 

Assert.assertEquals(

    actualMessage,

    "Invalid username or password"

);</code></pre>

<hr>

<h2>16. Returning Boolean from Page Methods</h2>

<p>Page Methods can return boolean values when the test needs to know whether an element or condition is present.</p>

<pre><code>public boolean isLoginButtonDisplayed() {

    return driver.findElement(loginButton)

                 .isDisplayed();

}</code></pre>

<p>Test:</p>

<pre><code>Assert.assertTrue(

    loginPage.isLoginButtonDisplayed()

);</code></pre>

<hr>

<h2>17. Returning WebElement from Page Methods</h2>

<p>Although Page Methods can technically return WebElement objects, exposing WebElements to test classes should generally be limited because it can expose page implementation details.</p>

<pre><code>public WebElement getLoginButton() {

    return driver.findElement(loginButton);

}</code></pre>

<p>In many cases, it is cleaner to provide a meaningful service method such as <code>clickLogin()</code> instead of returning the WebElement.</p>

<hr>

<h2>18. Returning Another Page Object</h2>

<p>When an action navigates to another page, the Page Method can return the corresponding Page Object.</p>

<pre><code>public HomePage clickLogin() {

 

    driver.findElement(loginButton).click();

 

    return new HomePage(driver);

}</code></pre>

<p>The test can then write:</p>

<pre><code>HomePage homePage = loginPage.clickLogin();</code></pre>

<p>This models the application's page-to-page navigation and keeps the test readable.</p>

<hr>

<h2>19. Page Methods for Navigation</h2>

<p>Navigation methods can represent actions that move the user from one page to another.</p>

<pre><code>public HomePage clickHome() {

    driver.findElement(homeLink).click();

    return new HomePage(driver);

}

 

public CartPage openCart() {

    driver.findElement(cartLink).click();

    return new CartPage(driver);

}</code></pre>

<p>Test:</p>

<pre><code>HomePage homePage = loginPage.clickHome();

CartPage cartPage = homePage.openCart();</code></pre>

<hr>

<h2>20. Page Methods for Search</h2>

<pre><code>public SearchResultsPage searchProduct(String product) {

 

    driver.findElement(searchBox)

          .clear();

 

    driver.findElement(searchBox)

          .sendKeys(product);

 

    driver.findElement(searchButton)

          .click();

 

    return new SearchResultsPage(driver);

}</code></pre>

<p>The test becomes:</p>

<pre><code>SearchResultsPage results =

    homePage.searchProduct("Laptop");</code></pre>

<hr>

<h2>21. Page Methods for Dropdowns</h2>

<p>Page Methods can encapsulate dropdown interaction.</p>

<pre><code>private By countryDropdown =

    By.id("country");

 

public void selectCountry(String country) {

 

    Select select =

        new Select(driver.findElement(countryDropdown));

 

    select.selectByVisibleText(country);

}</code></pre>

<p>Test:</p>

<pre><code>registrationPage.selectCountry("India");</code></pre>

<hr>

<h2>22. Page Methods for Checkboxes</h2>

<pre><code>private By termsCheckbox =

    By.id("terms");

 

public void acceptTerms() {

 

    WebElement checkbox =

        driver.findElement(termsCheckbox);

 

    if (!checkbox.isSelected()) {

        checkbox.click();

    }

}</code></pre>

<p>The method represents the business action rather than exposing the checkbox implementation.</p>

<hr>

<h2>23. Page Methods for Radio Buttons</h2>

<pre><code>private By maleRadio =

    By.id("male");

 

public void selectMaleGender() {

    driver.findElement(maleRadio).click();

}</code></pre>

<p>For reusable frameworks, a parameterized method can also be created:</p>

<pre><code>public void selectGender(String gender) {

 

    if (gender.equalsIgnoreCase("male")) {

        driver.findElement(By.id("male")).click();

    } else if (gender.equalsIgnoreCase("female")) {

        driver.findElement(By.id("female")).click();

    }

}</code></pre>

<hr>

<h2>24. Page Methods for Forms</h2>

<p>A complete form can be represented using multiple smaller Page Methods or one high-level method.</p>

<pre><code>public void enterName(String name) {

    driver.findElement(nameField).sendKeys(name);

}

 

public void enterEmail(String email) {

    driver.findElement(emailField).sendKeys(email);

}

 

public void enterMobile(String mobile) {

    driver.findElement(mobileField).sendKeys(mobile);

}

 

public void submitForm() {

    driver.findElement(submitButton).click();

}</code></pre>

<p>A high-level method can combine them:</p>

<pre><code>public void register(

        String name,

        String email,

        String mobile) {

 

    enterName(name);

    enterEmail(email);

    enterMobile(mobile);

    submitForm();

}</code></pre>

<hr>

<h2>25. Page Methods with Parameters</h2>

<p>Parameters make Page Methods reusable with different values.</p>

<pre><code>public void search(String keyword) {

 

    driver.findElement(searchBox)

          .clear();

 

    driver.findElement(searchBox)

          .sendKeys(keyword);

 

    driver.findElement(searchButton)

          .click();

}</code></pre>

<p>The same method can be used for multiple products:</p>

<pre><code>searchPage.search("Laptop");

searchPage.search("Mobile");

searchPage.search("Headphones");</code></pre>

<hr>

<h2>26. Page Methods with Multiple Parameters</h2>

<pre><code>public void login(

        String username,

        String password) {

 

    enterUsername(username);

    enterPassword(password);

    clickLogin();

}</code></pre>

<p>Multiple parameters are useful when an operation logically requires multiple inputs.</p>

<hr>

<h2>27. Page Methods and Data Providers</h2>

<p>Page Methods work effectively with TestNG Data Providers. The Data Provider supplies different input values while the Page Method performs the same UI operation.</p>

<pre><code>@DataProvider(name = "loginData")

public Object[][] loginData() {

    return new Object[][] {

        {"admin", "admin123"},

        {"manager", "manager123"},

        {"employee", "employee123"}

    };

}

 

@Test(dataProvider = "loginData")

public void loginTest(

        String username,

        String password) {

 

    loginPage.login(username, password);

}</code></pre>

<hr>

<h2>28. Page Methods and Assertions</h2>

<p>Page Objects should generally provide information or services, while test classes perform the assertions about expected application behavior.</p>

<pre><code>public String getPageTitle() {

    return driver.getTitle();

}</code></pre>

<p>Test class:</p>

<pre><code>String actualTitle =

    homePage.getPageTitle();

 

Assert.assertEquals(

    actualTitle,

    "Dashboard"

);</code></pre>

<p>This keeps verification logic in the test rather than embedding test expectations inside the Page Object.</p>

<hr>

<h2>29. Page Method for Error Messages</h2>

<pre><code>private By errorMessage =

    By.cssSelector(".error-message");

 

public String getErrorMessage() {

    return driver.findElement(errorMessage)

                 .getText();

}</code></pre>

<p>Test:</p>

<pre><code>Assert.assertEquals(

    loginPage.getErrorMessage(),

    "Invalid credentials"

);</code></pre>

<hr>

<h2>30. Page Method for Page Title</h2>

<pre><code>public String getPageTitle() {

    return driver.getTitle();

}</code></pre>

<p>Test:</p>

<pre><code>Assert.assertEquals(

    homePage.getPageTitle(),

    "Home Page"

);</code></pre>

<hr>

<h2>31. Page Method for URL</h2>

<pre><code>public String getCurrentUrl() {

    return driver.getCurrentUrl();

}</code></pre>

<p>Test:</p>

<pre><code>Assert.assertTrue(

    homePage.getCurrentUrl()

            .contains("/dashboard")

);</code></pre>

<hr>

<h2>32. Page Methods for Element State</h2>

<p>Page Methods can expose meaningful state information.</p>

<pre><code>public boolean isLogoutButtonVisible() {

    return driver.findElement(logoutButton)

                 .isDisplayed();

}

 

public boolean isLoginButtonEnabled() {

    return driver.findElement(loginButton)

                 .isEnabled();

}</code></pre>

<hr>

<h2>33. Page Methods with Explicit Wait</h2>

<p>When an operation depends on an element becoming available, a Page Method can encapsulate an explicit wait.</p>

<pre><code>private WebDriverWait wait;

 

public LoginPage(WebDriver driver) {

    this.driver = driver;

    this.wait = new WebDriverWait(

        driver,

        Duration.ofSeconds(10)

    );

}

 

public void clickLogin() {

 

    WebElement button =

        wait.until(

            ExpectedConditions.elementToBeClickable(

                loginButton

            )

        );

 

    button.click();

}</code></pre>

<p>This keeps synchronization logic close to the page element it belongs to.</p>

<hr>

<h2>34. Page Methods for Dynamic Elements</h2>

<p>Dynamic pages often require methods that locate elements at runtime.</p>

<pre><code>public void selectProduct(String productName) {

 

    By product =

        By.xpath(

            "//div[@class='product' and normalize-space()='" +

            productName +

            "']"

        );

 

    driver.findElement(product).click();

}</code></pre>

<p>The test can use:</p>

<pre><code>productPage.selectProduct("Laptop");</code></pre>

<hr>

<h2>35. Page Methods for Tables</h2>

<p>Page Methods can encapsulate operations performed on tables.</p>

<pre><code>public boolean isUserPresent(String username) {

 

    List&lt;WebElement&gt; rows =

        driver.findElements(

            By.cssSelector("table tbody tr")

        );

 

    for (WebElement row : rows) {

 

        if (row.getText()

               .contains(username)) {

            return true;

        }

    }

 

    return false;

}</code></pre>

<p>The test only needs to ask whether the user is present.</p>

<hr>

<h2>36. Page Methods for E-Commerce Cart</h2>

<pre><code>public void addProductToCart(String productName) {

 

    By addButton = By.xpath(

        "//div[contains(@class,'product')]" +

        "[.//h3[normalize-space()='" +

        productName +

        "']]//button"

    );

 

    driver.findElement(addButton).click();

}</code></pre>

<p>Test:</p>

<pre><code>productPage.addProductToCart("Laptop");

productPage.addProductToCart("Mouse");</code></pre>

<hr>

<h2>37. Page Methods for Checkout</h2>

<pre><code>public void enterShippingDetails(

        String name,

        String address,

        String city,

        String postalCode) {

 

    driver.findElement(nameField)

          .sendKeys(name);

 

    driver.findElement(addressField)

          .sendKeys(address);

 

    driver.findElement(cityField)

          .sendKeys(city);

 

    driver.findElement(postalCodeField)

          .sendKeys(postalCode);

}</code></pre>

<p>This method groups logically related actions into one reusable service.</p>

<hr>

<h2>38. Method Chaining in Page Objects</h2>

<p>Page Methods can return <code>this</code> when the action keeps the user on the same page. This allows method chaining.</p>

<pre><code>public LoginPage enterUsername(String username) {

 

    driver.findElement(usernameField)

          .sendKeys(username);

 

    return this;

}

 

public LoginPage enterPassword(String password) {

 

    driver.findElement(passwordField)

          .sendKeys(password);

 

    return this;

}</code></pre>

<p>The test can use:</p>

<pre><code>loginPage

    .enterUsername("admin")

    .enterPassword("admin123");</code></pre>

<hr>

<h2>39. Fluent Login Method</h2>

<p>A complete fluent workflow can be created using Page Methods.</p>

<pre><code>public LoginPage enterUsername(String username) {

    driver.findElement(usernameField)

          .sendKeys(username);

    return this;

}

 

public LoginPage enterPassword(String password) {

    driver.findElement(passwordField)

          .sendKeys(password);

    return this;

}

 

public HomePage submitLogin() {

    driver.findElement(loginButton).click();

    return new HomePage(driver);

}</code></pre>

<p>Test:</p>

<pre><code>HomePage homePage =

    loginPage

        .enterUsername("admin")

        .enterPassword("admin123")

        .submitLogin();</code></pre>

<hr>

<h2>40. Page Methods for Successful and Failed Actions</h2>

<p>The same UI action may have different expected destinations. For example, a successful login may navigate to a Home Page, while an unsuccessful login remains on the Login Page.</p>

<pre><code>public HomePage loginAs(

        String username,

        String password) {

 

    enterUsername(username);

    enterPassword(password);

    clickLogin();

 

    return new HomePage(driver);

}

 

public LoginPage loginExpectingFailure(

        String username,

        String password) {

 

    enterUsername(username);

    enterPassword(password);

    clickLogin();

 

    return new LoginPage(driver);

}</code></pre>

<hr>

<h2>41. Page Methods Should Represent User Actions</h2>

<p>A good Page Method usually represents something meaningful from the perspective of the user or application.</p>

<table border="1" cellpadding="8" cellspacing="0">

<tr><th>Less Meaningful</th><th>More Meaningful</th></tr>

<tr><td>clickElement()</td><td>clickLogin()</td></tr>

<tr><td>typeText()</td><td>enterUsername()</td></tr>

<tr><td>clickButton()</td><td>submitRegistration()</td></tr>

<tr><td>selectValue()</td><td>selectCountry()</td></tr>

<tr><td>clickLink()</td><td>openShoppingCart()</td></tr>

</table>

<p>Meaningful names make test cases easier to understand.</p>

<hr>

<h2>42. Avoid Exposing Page Internals</h2>

<p>A Page Object should hide implementation details wherever practical.</p>

<p>Instead of:</p>

<pre><code>loginPage.getUsernameElement().sendKeys("admin");

loginPage.getPasswordElement().sendKeys("admin123");

loginPage.getLoginButton().click();</code></pre>

<p>Prefer:</p>

<pre><code>loginPage.login("admin", "admin123");</code></pre>

<p>This allows the Page Object to control how the interaction is implemented.</p>

<hr>

<h2>43. Locators Should Stay Inside Page Classes</h2>

<p>Page Methods should normally use locators defined within the corresponding Page Object.</p>

<pre><code>public class LoginPage {

 

    private By username =

        By.id("username");

 

    private By password =

        By.id("password");

 

    private By loginButton =

        By.id("loginButton");

 

    public void login(

            String user,

            String pass) {

 

        driver.findElement(username)

              .sendKeys(user);

 

        driver.findElement(password)

              .sendKeys(pass);

 

        driver.findElement(loginButton)

              .click();

    }

}</code></pre>

<p>The test should not need to know the IDs.</p>

<hr>

<h2>44. Page Methods and Maintainability</h2>

<p>Suppose the login button changes from:</p>

<pre><code>By.id("loginButton")</code></pre>

<p>to:</p>

<pre><code>By.cssSelector(".login-btn")</code></pre>

<p>If the locator is centralized inside the Page Object, the Page Method can be updated in one place.</p>

<pre><code>private By loginButton =

    By.cssSelector(".login-btn");</code></pre>

<p>Tests calling <code>clickLogin()</code> do not need to know about the locator change.</p>

<hr>

<h2>45. Page Methods and Reusability</h2>

<p>The same Page Method can be reused across many tests.</p>

<pre><code>@Test

public void adminLogin() {

    loginPage.login("admin", "admin123");

}

 

@Test

public void managerLogin() {

    loginPage.login("manager", "manager123");

}

 

@Test

public void employeeLogin() {

    loginPage.login("employee", "employee123");

}</code></pre>

<p>Only the input data changes; the login implementation remains centralized.</p>

<hr>

<h2>46. Page Methods and Page Components</h2>

<p>Large applications may contain reusable components such as navigation bars, product cards, menus, filters, and headers. Page Methods can be created for these reusable components as well.</p>

<pre><code>public class NavigationBar {

 

    public void openCart() {

        driver.findElement(cartLink).click();

    }

 

    public void logout() {

        driver.findElement(logoutLink).click();

    }

}</code></pre>

<p>Page Objects can compose such reusable components instead of duplicating their methods across multiple pages.</p>

<hr>

<h2>47. Page Methods with Base Page</h2>

<p>A Base Page can contain common functionality shared by multiple Page Objects.</p>

<pre><code>public class BasePage {

 

    protected WebDriver driver;

    protected WebDriverWait wait;

 

    public BasePage(WebDriver driver) {

 

        this.driver = driver;

 

        this.wait = new WebDriverWait(

            driver,

            Duration.ofSeconds(10)

        );

    }

 

    public String getTitle() {

        return driver.getTitle();

    }

 

    public String getUrl() {

        return driver.getCurrentUrl();

    }

}</code></pre>

<p>Individual Page Objects can extend the Base Page.</p>

<hr>

<h2>48. Login Page Extending Base Page</h2>

<pre><code>public class LoginPage extends BasePage {

 

    private By username =

        By.id("username");

 

    private By password =

        By.id("password");

 

    private By loginButton =

        By.id("loginButton");

 

    public LoginPage(WebDriver driver) {

        super(driver);

    }

 

    public void login(

            String user,

            String pass) {

 

        driver.findElement(username)

              .sendKeys(user);

 

        driver.findElement(password)

              .sendKeys(pass);

 

        driver.findElement(loginButton)

              .click();

    }

}</code></pre>

<hr>

<h2>49. Page Methods and Test Readability</h2>

<p>Compare a test without Page Methods:</p>

<pre><code>driver.findElement(By.id("username"))

      .sendKeys("admin");

 

driver.findElement(By.id("password"))

      .sendKeys("admin123");

 

driver.findElement(By.id("loginButton"))

      .click();</code></pre>

<p>With Page Methods:</p>

<pre><code>loginPage.login(

    "admin",

    "admin123"

);</code></pre>

<p>The second version communicates the business action more clearly.</p>

<hr>

<h2>50. Page Methods and TestNG</h2>

<p>TestNG test methods can call Page Methods to perform application interactions and then use assertions to verify the results.</p>

<pre><code>@Test

public void validLoginTest() {

 

    LoginPage loginPage =

        new LoginPage(driver);

 

    HomePage homePage =

        loginPage.login(

            "admin",

            "admin123"

        );

 

    Assert.assertEquals(

        homePage.getPageTitle(),

        "Dashboard"

    );

}</code></pre>

<hr>

<h2>51. Page Methods and Data-Driven Testing</h2>

<p>Page Methods become especially powerful when combined with TestNG Data Providers.</p>

<pre><code>@DataProvider(name = "users")

public Object[][] users() {

    return new Object[][] {

        {"admin", "admin123"},

        {"manager", "manager123"},

        {"employee", "employee123"}

    };

}

 

@Test(dataProvider = "users")

public void loginTest(

        String username,

        String password) {

 

    loginPage.login(username, password);

}</code></pre>

<p>One Page Method handles all the login combinations.</p>

<hr>

<h2>52. Page Methods and Explicit Waits</h2>

<p>Synchronization should be encapsulated where appropriate instead of scattering waits throughout test classes.</p>

<pre><code>public void clickSubmit() {

 

    WebElement element =

        wait.until(

            ExpectedConditions

                .elementToBeClickable(submitButton)

        );

 

    element.click();

}</code></pre>

<p>This makes the test cleaner:</p>

<pre><code>registrationPage.clickSubmit();</code></pre>

<hr>

<h2>53. Page Methods and JavaScript</h2>

<p>JavaScript execution can be encapsulated inside a Page Method when a specific application interaction requires it.</p>

<pre><code>public void scrollToElement(By locator) {

 

    WebElement element =

        driver.findElement(locator);

 

    ((JavascriptExecutor) driver)

        .executeScript(

            "arguments[0].scrollIntoView(true);",

            element

        );

}</code></pre>

<p>However, normal Selenium interactions should generally be preferred when they work correctly.</p>

<hr>

<h2>54. Page Methods for Alerts</h2>

<pre><code>public void acceptAlert() {

 

    wait.until(

        ExpectedConditions.alertIsPresent()

    );

 

    driver.switchTo()

          .alert()

          .accept();

}</code></pre>

<p>The test can simply call:</p>

<pre><code>alertPage.acceptAlert();</code></pre>

<hr>

<h2>55. Page Methods for Frames</h2>

<pre><code>public void switchToPaymentFrame() {

 

    WebElement frame =

        driver.findElement(paymentFrame);

 

    driver.switchTo()

          .frame(frame);

}</code></pre>

<p>A separate method can return to the main document:</p>

<pre><code>public void switchToDefaultContent() {

    driver.switchTo().defaultContent();

}</code></pre>

<hr>

<h2>56. Page Methods for Windows and Tabs</h2>

<pre><code>public void switchToNewWindow() {

 

    String currentWindow =

        driver.getWindowHandle();

 

    for (String window :

            driver.getWindowHandles()) {

 

        if (!window.equals(currentWindow)) {

            driver.switchTo()

                  .window(window);

            break;

        }

    }

}</code></pre>

<hr>

<h2>57. Page Methods for File Upload</h2>

<p>File upload can be encapsulated in a Page Method.</p>

<pre><code>public void uploadFile(String filePath) {

 

    driver.findElement(uploadInput)

          .sendKeys(filePath);

}</code></pre>

<p>Test:</p>

<pre><code>profilePage.uploadFile(

    "C:\\files\\profile.png"

);</code></pre>

<hr>

<h2>58. Page Methods for Mouse Hover</h2>

<pre><code>public void hoverOverProducts() {

 

    WebElement products =

        driver.findElement(productsMenu);

 

    Actions actions =

        new Actions(driver);

 

    actions.moveToElement(products)

           .perform();

}</code></pre>

<hr>

<h2>59. Page Methods for Drag and Drop</h2>

<pre><code>public void dragProductToCart() {

 

    WebElement product =

        driver.findElement(productElement);

 

    WebElement cart =

        driver.findElement(cartElement);

 

    Actions actions =

        new Actions(driver);

 

    actions.dragAndDrop(

        product,

        cart

    ).perform();

}</code></pre>

<hr>

<h2>60. Page Methods for Scrolling</h2>

<pre><code>public void scrollToBottom() {

 

    ((JavascriptExecutor) driver)

        .executeScript(

            "window.scrollTo(0, document.body.scrollHeight)"

        );

}</code></pre>

<hr>

<h2>61. Page Methods for Getting Product Information</h2>

<pre><code>public String getProductName() {

    return driver.findElement(productName)

                 .getText();

}

 

public String getProductPrice() {

    return driver.findElement(productPrice)

                 .getText();

}</code></pre>

<p>Test:</p>

<pre><code>Assert.assertEquals(

    productPage.getProductName(),

    "Laptop"

);

 

Assert.assertEquals(

    productPage.getProductPrice(),

    "$999"

);</code></pre>

<hr>

<h2>62. Page Methods for Cart Operations</h2>

<pre><code>public void removeProduct(String product) {

 

    By removeButton = By.xpath(

        "//div[@class='cart-item']" +

        "[.//span[normalize-space()='" +

        product +

        "']]//button"

    );

 

    driver.findElement(removeButton)

          .click();

}

 

public void proceedToCheckout() {

 

    driver.findElement(checkoutButton)

          .click();

}</code></pre>

<hr>

<h2>63. Page Methods for Login Validation</h2>

<pre><code>public boolean isLoginErrorDisplayed() {

 

    try {

        return driver.findElement(errorMessage)

                     .isDisplayed();

    } catch (NoSuchElementException e) {

        return false;

    }

}</code></pre>

<p>The test can verify:</p>

<pre><code>Assert.assertTrue(

    loginPage.isLoginErrorDisplayed()

);</code></pre>

<hr>

<h2>64. Complete Page Method Example</h2>

<pre><code>import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

 

public class LoginPage {

 

    private WebDriver driver;

 

    private By usernameField =

        By.id("username");

 

    private By passwordField =

        By.id("password");

 

    private By loginButton =

        By.id("loginButton");

 

    private By errorMessage =

        By.id("errorMessage");

 

    public LoginPage(WebDriver driver) {

        this.driver = driver;

    }

 

    public void enterUsername(String username) {

 

        driver.findElement(usernameField)

              .clear();

 

        driver.findElement(usernameField)

              .sendKeys(username);

    }

 

    public void enterPassword(String password) {

 

        driver.findElement(passwordField)

              .clear();

 

        driver.findElement(passwordField)

              .sendKeys(password);

    }

 

    public void clickLogin() {

        driver.findElement(loginButton)

              .click();

    }

 

    public HomePage login(

            String username,

            String password) {

 

        enterUsername(username);

        enterPassword(password);

        clickLogin();

 

        return new HomePage(driver);

    }

 

    public String getErrorMessage() {

 

        return driver.findElement(errorMessage)

                    .getText();

    }

}</code></pre>

<hr>

<h2>65. Complete Test Using Page Methods</h2>

<pre><code>import org.testng.Assert;

import org.testng.annotations.Test;

 

public class LoginTest {

 

    @Test

    public void validLoginTest() {

 

        LoginPage loginPage =

            new LoginPage(driver);

 

        HomePage homePage =

            loginPage.login(

                "admin",

                "admin123"

            );

 

        Assert.assertEquals(

            homePage.getPageTitle(),

            "Dashboard"

        );

    }

 

    @Test

    public void invalidLoginTest() {

 

        LoginPage loginPage =

            new LoginPage(driver);

 

        loginPage.enterUsername("invalid");

        loginPage.enterPassword("wrong");

        loginPage.clickLogin();

 

        Assert.assertEquals(

            loginPage.getErrorMessage(),

            "Invalid credentials"

        );

    }

}</code></pre>

<hr>

<h2>66. Page Methods vs Direct Selenium Commands</h2>

<table border="1" cellpadding="8" cellspacing="0">

<tr><th>Direct Selenium in Test</th><th>Page Methods</th></tr>

<tr><td>Locators exposed in tests</td><td>Locators encapsulated</td></tr>

<tr><td>More duplicate code</td><td>Less duplicate code</td></tr>

<tr><td>Harder to read</td><td>More readable</td></tr>

<tr><td>UI changes affect many tests</td><td>UI changes can often be handled in Page Objects</td></tr>

<tr><td>Less reusable</td><td>Highly reusable</td></tr>

<tr><td>Test and UI logic mixed</td><td>Test and UI logic separated</td></tr>

</table>

<hr>

<h2>67. Good Page Method Naming</h2>

<p>Page Method names should describe the action or service clearly.</p>

<ul>

<li><code>enterUsername()</code></li>

<li><code>enterPassword()</code></li>

<li><code>clickLogin()</code></li>

<li><code>searchProduct()</code></li>

<li><code>selectCategory()</code></li>

<li><code>addProductToCart()</code></li>

<li><code>removeProduct()</code></li>

<li><code>proceedToCheckout()</code></li>

<li><code>getProductPrice()</code></li>

<li><code>isErrorMessageDisplayed()</code></li>

</ul>

<p>Avoid unclear names such as <code>method1()</code>, <code>clickSomething()</code>, or <code>performAction()</code>.</p>

<hr>

<h2>68. Common Mistakes in Page Methods</h2>

<ul>

<li>Putting all Selenium code directly in test classes.</li>

<li>Exposing locators unnecessarily.</li>

<li>Using unclear method names.</li>

<li>Creating extremely large methods that perform unrelated actions.</li>

<li>Duplicating the same Selenium interaction in multiple methods.</li>

<li>Putting test assertions throughout Page Objects.</li>

<li>Hard-coding test data unnecessarily inside Page Methods.</li>

<li>Using Thread.sleep() everywhere instead of proper synchronization.</li>

<li>Sharing unsafe WebDriver instances between parallel tests.</li>

<li>Making Page Methods dependent on unrelated pages.</li>

<li>Returning WebElements when a higher-level service method would be clearer.</li>

</ul>

<hr>

<h2>69. Best Practices for Page Methods</h2>

<ul>

<li>Keep Page Methods focused on page behavior.</li>

<li>Use meaningful method names.</li>

<li>Keep locators private where practical.</li>

<li>Keep test assertions in test classes.</li>

<li>Return another Page Object when navigation occurs.</li>

<li>Return <code>this</code> when fluent chaining is appropriate.</li>

<li>Use parameters for reusable actions.</li>

<li>Keep synchronization close to the interaction that requires it.</li>

<li>Reuse smaller methods inside larger workflow methods.</li>

<li>Avoid duplicating Selenium code.</li>

<li>Keep Page Objects independent of specific test scenarios.</li>

<li>Use Data Providers for large sets of test data rather than duplicating Page Methods.</li>

<li>Keep sensitive information out of source-controlled test code.</li>

</ul>

<hr>

<h2>70. Page Methods and Single Responsibility</h2>

<p>A Page Method should generally have one clear responsibility.</p>

<p>For example:</p>

<pre><code>public void enterUsername(String username) {

    // Only enters username

}</code></pre>

<p>A complete workflow can then combine focused methods:</p>

<pre><code>public HomePage login(

        String username,

        String password) {

 

    enterUsername(username);

    enterPassword(password);

    return submitLogin();

}</code></pre>

<p>This structure improves reuse because individual methods can be used independently when required.</p>

<hr>

<h2>71. Page Methods and Abstraction</h2>

<p>Page Methods provide abstraction by hiding Selenium implementation details from test classes.</p>

<pre><code>Test:

loginPage.login("admin", "admin123");</code></pre>

<p>The test does not need to know whether the Page Object uses:</p>

<ul>

<li><code>By.id()</code></li>

<li><code>By.name()</code></li>

<li><code>By.cssSelector()</code></li>

<li><code>By.xpath()</code></li>

<li>Explicit waits</li>

<li>JavaScript execution</li>

<li>Actions API</li>

</ul>

<p>Those implementation details remain inside the Page Object.</p>

<hr>

<h2>72. Page Methods and Encapsulation</h2>

<p>Encapsulation means keeping page-specific implementation details inside the Page Object and exposing meaningful public methods to the test.</p>

<pre><code>private By loginButton =

    By.id("loginButton");

 

public void clickLogin() {

    driver.findElement(loginButton).click();

}</code></pre>

<p>The locator is private, while the page service is public.</p>

<hr>

<h2>73. Page Methods and Page Navigation Flow</h2>

<pre><code>LoginPage

    |

    | login()

    v

HomePage

    |

    | searchProduct()

    v

SearchResultsPage

    |

    | addProductToCart()

    v

CartPage

    |

    | proceedToCheckout()

    v

CheckoutPage

    |

    | placeOrder()

    v

OrderConfirmationPage</code></pre>

<p>This structure models the user's journey through the application and keeps navigation logic inside the relevant Page Objects.</p>

<hr>

<h2>74. Practical E-Commerce Page Methods</h2>

<pre><code>public class ProductPage {

 

    private WebDriver driver;

 

    public ProductPage(WebDriver driver) {

        this.driver = driver;

    }

 

    public void selectProduct(String product) {

        // Product selection logic

    }

 

    public void selectQuantity(int quantity) {

        // Quantity selection logic

    }

 

    public CartPage addToCart() {

 

        // Add product logic

 

        return new CartPage(driver);

    }

}</code></pre>

<p>Test:</p>

<pre><code>CartPage cartPage =

    productPage

        .selectProduct("Laptop")

        .addToCart();</code></pre>

<hr>

<h2>75. Practical Login Framework Structure</h2>

<pre><code>src

|-- test

    |-- java

        |-- pages

        |   |-- LoginPage.java

        |   |-- HomePage.java

        |   |-- ProductPage.java

        |   |-- CartPage.java

        |   |-- CheckoutPage.java

        |

        |-- tests

        |   |-- LoginTest.java

        |   |-- ProductTest.java

        |   |-- CheckoutTest.java

        |

        |-- utilities

            |-- DriverFactory.java

            |-- ConfigReader.java

            |-- ExcelReader.java</code></pre>

<p>The <code>pages</code> package contains Page Objects and their Page Methods, while the <code>tests</code> package contains test scenarios and assertions.</p>

<hr>

<h2>76. Real-World Page Method Architecture</h2>

<pre><code>Test Data

    |

    v

Test Class

    |

    v

Page Method

    |

    v

Page Object

    |

    +-- Locators

    |

    +-- Synchronization

    |

    +-- Selenium Actions

    |

    v

Web Application

    |

    v

Page Result

    |

    v

Assertion

    |

    v

Test Report</code></pre>

<hr>

<h2>77. Page Methods with Page Object Components</h2>

<p>Modern applications often contain reusable components such as headers, navigation bars, product cards, filters, menus, and tables. These components can have their own methods.</p>

<pre><code>public class HeaderComponent {

 

    public void openCart() {

        // Open cart

    }

 

    public void logout() {

        // Logout

    }

}

 

public class ProductComponent {

 

    public String getProductName() {

        return "";

    }

 

    public void addToCart() {

        // Add product

    }

}</code></pre>

<p>This component-based approach can reduce duplication in applications where the same UI sections appear on many pages.</p>

<hr>

<h2>78. Page Methods and Reusable Business Workflows</h2>

<p>High-level Page Methods can represent complete business workflows.</p>

<pre><code>public OrderConfirmationPage purchaseProduct(

        String productName,

        int quantity) {

 

    selectProduct(productName);

    selectQuantity(quantity);

    addToCart();

 

    return checkout();

}</code></pre>

<p>Test:</p>

<pre><code>OrderConfirmationPage confirmation =

    productPage.purchaseProduct(

        "Laptop",

        1

    );</code></pre>

<hr>

<h2>79. Page Methods Should Not Become God Methods</h2>

<p>A common mistake is creating one huge Page Method that performs an entire end-to-end business process, including unrelated pages, data setup, assertions, and cleanup.</p>

<p>Instead of:</p>

<pre><code>performEverything();</code></pre>

<p>prefer focused methods:</p>

<pre><code>login();

searchProduct();

addProductToCart();

proceedToCheckout();

placeOrder();</code></pre>

<p>These methods can still be combined into a higher-level workflow when that workflow is genuinely useful.</p>

<hr>

<h2>80. Page Methods and Assertions - Recommended Pattern</h2>

<p>A Page Object should generally expose information that a test can verify instead of performing the verification itself.</p>

<p>Page Object:</p>

<pre><code>public String getWelcomeMessage() {

    return driver.findElement(welcomeMessage)

                 .getText();

}</code></pre>

<p>Test:</p>

<pre><code>Assert.assertEquals(

    homePage.getWelcomeMessage(),

    "Welcome Admin"

);</code></pre>

<p>This keeps the expected test outcome in the test class.</p>

<hr>

<h2>81. Page Methods and Error Handling</h2>

<p>Page Methods should fail clearly when an expected application interaction cannot be completed. Framework-specific exception handling can be added where it provides useful diagnostic information.</p>

<pre><code>public void clickLogin() {

 

    try {

        driver.findElement(loginButton)

              .click();

    } catch (NoSuchElementException e) {

        throw new RuntimeException(

            "Login button was not found",

            e

        );

    }

}</code></pre>

<p>In larger frameworks, custom exceptions and centralized logging may be used instead of generic exception wrapping.</p>

<hr>

<h2>82. Page Methods and Logging</h2>

<p>Logging can help identify which Page Method was executing when a failure occurred.</p>

<pre><code>public void login(

        String username,

        String password) {

 

    System.out.println(

        "Executing login for user: " + username

    );

 

    enterUsername(username);

    enterPassword(password);

    clickLogin();

}</code></pre>

<p>In production frameworks, a logging framework such as SLF4J with an appropriate backend is generally preferable to extensive <code>System.out.println()</code> usage.</p>

<hr>

<h2>83. Page Methods and Screenshots</h2>

<p>Screenshot handling is often better centralized in a utility or reporting layer, but Page Methods can expose meaningful state information that helps the reporting layer identify where a failure occurred.</p>

<pre><code>public String getPageName() {

    return "Login Page";

}</code></pre>

<p>The reporting framework can use such information together with the failed test and screenshot.</p>

<hr>

<h2>84. Page Methods and Parallel Execution</h2>

<p>When Selenium tests execute in parallel, each test execution should generally use an isolated WebDriver session. Page Objects should use the driver associated with the current test instance rather than sharing an unsafe static driver across threads.</p>

<pre><code>Test Thread 1

    |

    v

Driver 1

    |

    v

LoginPage 1

 

Test Thread 2

    |

    v

Driver 2

    |

    v

LoginPage 2</code></pre>

<hr>

<h2>85. Page Methods with Thread-Safe Driver Management</h2>

<p>A framework can use a Driver Factory or ThreadLocal-based design to provide an isolated driver to each parallel test thread.</p>

<pre><code>public class DriverFactory {

 

    private static ThreadLocal&lt;WebDriver&gt; driver =

        new ThreadLocal&lt;&gt;();

 

    public static void setDriver(

            WebDriver webDriver) {

 

        driver.set(webDriver);

    }

 

    public static WebDriver getDriver() {

        return driver.get();

    }

 

    public static void quitDriver() {

 

        if (driver.get() != null) {

            driver.get().quit();

            driver.remove();

        }

    }

}</code></pre>

<hr>

<h2>86. Page Methods and Page Factory</h2>

<p>Page Factory is one possible implementation style for page objects. It can use annotations such as <code>@FindBy</code> to represent page elements. Page Factory is related to POM but is not the same concept: POM is the design pattern, while Page Factory is a mechanism that can be used to initialize page elements.</p>

<pre><code>public class LoginPage {

 

    private WebDriver driver;

 

    @FindBy(id = "username")

    private WebElement username;

 

    @FindBy(id = "password")

    private WebElement password;

 

    @FindBy(id = "loginButton")

    private WebElement loginButton;

 

    public LoginPage(WebDriver driver) {

        this.driver = driver;

        PageFactory.initElements(

            driver,

            this

        );

    }

 

    public void login(

            String user,

            String pass) {

 

        username.sendKeys(user);

        password.sendKeys(pass);

        loginButton.click();

    }

}</code></pre>

<hr>

<h2>87. Page Methods Using By Locators vs WebElements</h2>

<table border="1" cellpadding="8" cellspacing="0">

<tr><th>By Locators</th><th>WebElement Fields</th></tr>

<tr><td>Locators are stored as By objects</td><td>Elements are represented as WebElement fields</td></tr>

<tr><td>Elements can be found when the method needs them</td><td>Often initialized through Page Factory or explicit lookup</td></tr>

<tr><td>Works naturally with explicit waits</td><td>Can be convenient for traditional POM styles</td></tr>

<tr><td>Common modern Selenium approach</td><td>Common in traditional Page Factory implementations</td></tr>

</table>

<hr>

<h2>88. Practical Complete POM Example</h2>

<pre><code>public class LoginPage {

 

    private final WebDriver driver;

 

    private final By username =

        By.id("username");

 

    private final By password =

        By.id("password");

 

    private final By loginButton =

        By.id("loginButton");

 

    public LoginPage(WebDriver driver) {

        this.driver = driver;

    }

 

    public LoginPage enterUsername(

            String value) {

 

        driver.findElement(username)

              .clear();

 

        driver.findElement(username)

              .sendKeys(value);

 

        return this;

    }

 

    public LoginPage enterPassword(

            String value) {

 

        driver.findElement(password)

              .clear();

 

        driver.findElement(password)

              .sendKeys(value);

 

        return this;

    }

 

    public HomePage submitLogin() {

 

        driver.findElement(loginButton)

              .click();

 

        return new HomePage(driver);

    }

 

    public HomePage login(

            String username,

            String password) {

 

        return enterUsername(username)

            .enterPassword(password)

            .submitLogin();

    }

}</code></pre>

<hr>

<h2>89. Complete Test Using the POM</h2>

<pre><code>public class LoginTest {

 

    @Test

    public void validLoginTest() {

 

        LoginPage loginPage =

            new LoginPage(driver);

 

        HomePage homePage =

            loginPage.login(

                "admin",

                "admin123"

            );

 

        Assert.assertEquals(

            homePage.getPageTitle(),

            "Dashboard"

        );

    }

}</code></pre>

<p>The test expresses the user workflow without exposing the underlying Selenium locators.</p>

<hr>

<h2>90. Advantages of Page Methods</h2>

<ul>

<li><strong>Reusability:</strong> The same method can be used by multiple tests.</li>

<li><strong>Maintainability:</strong> UI implementation details are centralized.</li>

<li><strong>Readability:</strong> Test cases become closer to business workflows.</li>

<li><strong>Abstraction:</strong> Tests do not need to know locator implementation details.</li>

<li><strong>Encapsulation:</strong> Page-specific data and behavior stay together.</li>

<li><strong>Scalability:</strong> The approach works well as the automation suite grows.</li>

<li><strong>Reduced Duplication:</strong> Common Selenium operations are implemented once.</li>

<li><strong>Better Collaboration:</strong> Team members can understand page services more easily.</li>

<li><strong>Easier UI Maintenance:</strong> Locator changes can often be handled inside Page Objects.</li>

</ul>

<hr>

<h2>91. Limitations and Considerations</h2>

<ul>

<li>Poorly designed Page Objects can become very large.</li>

<li>Overly generic Page Methods can become difficult to understand.</li>

<li>Complex workflows may require multiple Page Objects and components.</li>

<li>Incorrect abstraction can hide important test behavior.</li>

<li>Excessive method chaining can reduce readability.</li>

<li>Page Methods should not contain unrelated test logic.</li>

<li>Large frameworks require consistent naming and architectural conventions.</li>

</ul>

<hr>

<h2>92. Page Methods vs Hard-Coded Selenium</h2>

<table border="1" cellpadding="8" cellspacing="0">

<tr><th>Hard-Coded Selenium</th><th>Page Methods</th></tr>

<tr><td>Locators repeated in tests</td><td>Locators centralized</td></tr>

<tr><td>UI logic mixed with validation</td><td>UI logic separated</td></tr>

<tr><td>Difficult to maintain</td><td>Easier to maintain</td></tr>

<tr><td>Low reusability</td><td>High reusability</td></tr>

<tr><td>Tests become verbose</td><td>Tests become concise</td></tr>

<tr><td>UI changes may affect many tests</td><td>Changes can often be isolated to Page Objects</td></tr>

</table>

<hr>

<h2>93. Page Methods vs Utility Methods</h2>

<table border="1" cellpadding="8" cellspacing="0">

<tr><th>Page Method</th><th>Utility Method</th></tr>

<tr><td>Specific to a page/component</td><td>Usually generic and reusable</td></tr>

<tr><td>Uses page-specific locators</td><td>Usually independent of a particular page</td></tr>

<tr><td>Example: login()</td><td>Example: takeScreenshot()</td></tr>

<tr><td>Example: addProductToCart()</td><td>Example: readExcel()</td></tr>

<tr><td>Represents page behavior</td><td>Provides framework support</td></tr>

</table>

<hr>

<h2>94. Recommended Page Method Design</h2>

<pre><code>Page Object

    |

    +-- Private Locators

    |

    +-- Constructor

    |

    +-- Small Interaction Methods

    |      |

    |      +-- enterUsername()

    |      +-- enterPassword()

    |      +-- clickLogin()

    |

    +-- High-Level Workflow Methods

    |      |

    |      +-- login()

    |      +-- register()

    |

    +-- Information Methods

           |

           +-- getErrorMessage()

           +-- getPageTitle()

           +-- isElementDisplayed()</code></pre>

<hr>

<h2>95. Interview Questions on Page Methods</h2>

<h3>1. What is a Page Method?</h3>

<p>A Page Method is a method inside a Page Object that represents an action, operation, or service provided by a web page or component.</p>

<h3>2. Why are Page Methods used in Selenium?</h3>

<p>They encapsulate Selenium interaction logic, reduce duplication, improve readability, and make automation code easier to maintain.</p>

<h3>3. Where should Page Methods be created?</h3>

<p>They are normally created inside Page Object classes representing application pages or reusable page components.</p>

<h3>4. Should locators be written inside test classes?</h3>

<p>In a POM design, page-specific locators are generally kept inside the corresponding Page Object rather than duplicated across tests.</p>

<h3>5. Can a Page Method accept parameters?</h3>

<p>Yes. Parameters make Page Methods reusable with different input values.</p>

<h3>6. Can a Page Method return a value?</h3>

<p>Yes. It can return strings, booleans, numbers, collections, Page Objects, or other appropriate values.</p>

<h3>7. Can a Page Method return another Page Object?</h3>

<p>Yes. This is useful when an action navigates to another page.</p>

<h3>8. What is method chaining in POM?</h3>

<p>Method chaining occurs when Page Methods return <code>this</code> or another Page Object so multiple operations can be called in a fluent sequence.</p>

<h3>9. Should Page Methods contain assertions?</h3>

<p>Generally, Page Objects should provide page services and information, while tests should contain assertions about expected behavior.</p>

<h3>10. What is the difference between a Page Method and a Test Method?</h3>

<p>A Page Method performs page interaction, while a Test Method represents and validates a test scenario.</p>

<h3>11. Can Page Methods use explicit waits?</h3>

<p>Yes. Synchronization for page-specific elements can be encapsulated within Page Methods where appropriate.</p>

<h3>12. Can Data Providers call Page Methods?</h3>

<p>Yes. TestNG Data Providers can supply data to test methods, and those test methods can call reusable Page Methods.</p>

<h3>13. Why should Page Methods have meaningful names?</h3>

<p>Meaningful names make tests easier to understand and allow the Page Object to communicate application behavior clearly.</p>

<h3>14. What is a high-level Page Method?</h3>

<p>A high-level Page Method represents a complete logical workflow, such as <code>login()</code>, <code>registerUser()</code>, or <code>checkout()</code>.</p>

<h3>15. What is a low-level Page Method?</h3>

<p>A low-level Page Method usually performs one focused interaction, such as entering text or clicking a specific button.</p>

<h3>16. Can Page Methods be used with Page Factory?</h3>

<p>Yes. Page Factory can be used to initialize page elements while Page Methods define the operations performed on those elements.</p>

<h3>17. How do Page Methods improve maintenance?</h3>

<p>They centralize page-specific interaction logic, so changes to UI locators or interaction details can often be handled in one Page Object.</p>

<h3>18. Can Page Methods be used for dynamic elements?</h3>

<p>Yes. A Page Method can construct dynamic locators based on method parameters.</p>

<h3>19. Can Page Methods be reused across multiple tests?</h3>

<p>Yes. Reusability is one of the primary benefits of Page Object design.</p>

<h3>20. What is the most important principle when designing Page Methods?</h3>

<p>Page Methods should clearly represent the services or behaviors of the page while hiding unnecessary implementation details from the test.</p>

<hr>

<h2>96. Quick Reference Table</h2>

<table border="1" cellpadding="8" cellspacing="0">

<tr><th>Concept</th><th>Example</th><th>Purpose</th></tr>

<tr><td>Page Method</td><td>login()</td><td>Represents page behavior</td></tr>

<tr><td>Input Method</td><td>enterUsername()</td><td>Enters data</td></tr>

<tr><td>Click Method</td><td>clickLogin()</td><td>Performs click action</td></tr>

<tr><td>Getter Method</td><td>getErrorMessage()</td><td>Reads page information</td></tr>

<tr><td>Boolean Method</td><td>isLoginDisplayed()</td><td>Returns page state</td></tr>

<tr><td>Navigation Method</td><td>openCart()</td><td>Navigates to another page</td></tr>

<tr><td>Workflow Method</td><td>login()</td><td>Combines multiple actions</td></tr>

<tr><td>Fluent Method</td><td>enterUsername()</td><td>Returns this for chaining</td></tr>

<tr><td>Page Transition</td><td>submitLogin()</td><td>Returns another Page Object</td></tr>

</table>

<hr>

<h2>97. Learning Roadmap for Page Methods</h2>

<ol>

<li>Understand Selenium WebDriver basics.</li>

<li>Learn the Page Object Model.</li>

<li>Create basic Page Classes.</li>

<li>Define private page locators.</li>

<li>Create simple Page Methods.</li>

<li>Pass parameters to Page Methods.</li>

<li>Return values from Page Methods.</li>

<li>Return other Page Objects after navigation.</li>

<li>Learn fluent Page Methods and method chaining.</li>

<li>Use explicit waits inside appropriate Page Methods.</li>

<li>Combine Page Methods with TestNG.</li>

<li>Combine Page Methods with Data Providers.</li>

<li>Build reusable Page Components.</li>

<li>Create Base Page functionality.</li>

<li>Integrate Page Objects with Driver Factory.</li>

<li>Build a complete scalable Selenium automation framework.</li>

</ol>

<hr>

<h2>98. Practical Exercises</h2>

<ol>

<li>Create a LoginPage class with username and password methods.</li>

<li>Create a clickLogin() Page Method.</li>

<li>Create a login() workflow method.</li>

<li>Create a method that returns the login error message.</li>

<li>Create a HomePage with logout functionality.</li>

<li>Create a SearchPage with a parameterized searchProduct() method.</li>

<li>Create a ProductPage with addProductToCart().</li>

<li>Create a CartPage with removeProduct() and proceedToCheckout().</li>

<li>Create Page Methods for an e-commerce checkout workflow.</li>

<li>Use TestNG DataProvider with login().</li>

<li>Implement fluent Page Methods using method chaining.</li>

<li>Implement Page Methods that return another Page Object after navigation.</li>

<li>Add explicit waits to important Page Methods.</li>

<li>Create reusable Header and Navigation components.</li>

<li>Build a complete Selenium POM project using Page Methods.</li>

</ol>

<hr>

<h2>99. Real-World Page Method Flow</h2>

<pre><code>Test Case

    |

    v

loginPage.login(username, password)

    |

    +-- enterUsername()

    |

    +-- enterPassword()

    |

    +-- clickLogin()

    |

    v

HomePage

    |

    +-- searchProduct()

    |

    v

SearchResultsPage

    |

    +-- selectProduct()

    |

    v

ProductPage

    |

    +-- addToCart()

    |

    v

CartPage

    |

    +-- proceedToCheckout()

    |

    v

CheckoutPage

    |

    +-- placeOrder()

    |

    v

OrderConfirmationPage

    |

    v

Assertions / Test Report</code></pre>

<hr>

<h2>100. Summary</h2>

<p>Page Methods are an essential part of a maintainable Selenium Page Object Model. They represent the actions and services provided by a web page while hiding the underlying Selenium implementation from test classes.</p>

<p>A good Page Method should have a clear responsibility, meaningful name, appropriate parameters, and a useful return type when required. Small interaction methods such as <code>enterUsername()</code> and <code>clickLogin()</code> can be combined into higher-level workflow methods such as <code>login()</code>.</p>

<p>Page Methods can return strings, booleans, collections, <code>this</code>, or other Page Objects depending on the operation. Returning another Page Object is particularly useful for modeling page navigation, while returning <code>this</code> can support fluent method chaining.</p>

<p>Page Methods work especially well with TestNG, Data Providers, explicit waits, Page Components, Page Factory, Driver Factory, reporting, and CI/CD frameworks. They help keep Selenium locators and interaction logic centralized while allowing test classes to focus on business scenarios and assertions.</p>

<p><strong>Final Takeaway:</strong> A well-designed Page Method should make a Selenium test read like a user workflow while keeping the technical details of locators, WebDriver commands, synchronization, and page structure inside the Page Object.</p>

<hr>

<h2>101. Course Resources</h2>

<ul>

<li><a href="https://www.justacademy.co/course-detail/selenium-training" target="_blank" rel="noopener noreferrer">Selenium Training</a></li>

<li><a href="https://www.justacademy.co/register-for-course-demo" target="_blank" rel="noopener noreferrer">Register for Selenium Course Demo</a></li>

</ul>

</div>

Previous Next
whatsapp